package com.sunkai.math;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream.PutField;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.learn.datainjector.A;


public class ReadFile {
	
	public String read(InputStream in) throws IOException {
		byte[] b = new byte[in.available()];
		in.read(b);
		in.close();
		return new String(b);
	}
	
	public List<String> getLine(String text) {
		List<String> list = new ArrayList<String>();
		if (text == null || text.trim().length() == 0) {
			return list;
		}
		String[] strArr = text.replace("\r", "").split("\n");
		for (String str : strArr) {
			str = str.trim();
			if (str.length() > 0 && str.charAt(0) != '#') {
				list.add(str);
			}
		}
		return list;
	}
	
	public Map<String, String> parseToMap(List<String> list) {
		Map<String, String> map = new LinkedHashMap<String, String>();
		if (list == null || list.size() == 0) {
			return map;
		}
		for (String str : list) {
			int index = str.indexOf("=");
			if (index == -1) {
				continue;
			}
			String key = str.substring(0, index);
			String value = getValue(str.substring(index+1));
			map.put(key, value);
		}
		return map;
	}
	
	private String getValue(String value) {
		//
		return value;
	}
	
	public <T>T mapToObjectV2(Map<String, String> map, Class clazz) throws InstantiationException, IllegalAccessException {
		Object object = clazz.newInstance();
		if (map == null || map.size() == 0) {
			return (T) object;
		}
		Set<Entry<String, String>> entrySet = map.entrySet();
		for (Entry<String, String> entry : entrySet) {
			String key = entry.getKey();
			String value = entry.getValue();
			if (key.indexOf(".") == -1) {
				continue;
			}
			inject(key, value, object);
		}
		
		return (T) object;
	}
	
	private void inject(String key, String value, Object beforeObject) throws SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
		String[] array = key.split("\\.");
		for (int i=1;i < array.length;i++) {
			//忽略obj.b.c.name的obj
			String fieldName = array[i];
			Object thisObj = null;
			/*if (i == 0) {
				thisObj = beforeObject;
			}*/
			if (i != array.length-1) {
				//对象
				try {
					Class beforeClazz = beforeObject.getClass();
					Field field = beforeClazz.getDeclaredField(fieldName);
					field.setAccessible(true);
					if (field.get(beforeObject) == null) {
						//初始化对象，反射注入field
						Class thisClass = field.getType();//获取当前属性对象class
						Object inObj = thisClass.newInstance();
						field.set(beforeObject, inObj);
						//递归
						inject(key, value, inObj);
					}
				} catch (Exception e) {
					// TODO: handle exception
				}
			} else {
				//属性
				injectField(fieldName, value, beforeObject);
			}
		}
	}
	
	public <T>T mapToObject(Map<String, String> map, Class clazz) throws InstantiationException, IllegalAccessException, NumberFormatException, NoSuchFieldException, SecurityException, IllegalArgumentException {                       
		Object object = clazz.newInstance();
		if (map == null || map.size() == 0) {
			return (T) object;
		}
		Set<Entry<String, String>> entrySet = map.entrySet();
		Map<String, Object> objMap = new LinkedHashMap<String, Object>();
		for (Entry<String, String> entry : entrySet) {
			String key = entry.getKey();
			String value = entry.getValue();
			if (key.indexOf(".") == -1) {
				continue;
			}
			String[] array = key.split("\\.");
			String left = "";
			for (int i=0;i<array.length;i++) {
				
				String beforeKey = left;
				if (left.length() == 0) {
					left += array[i];
					objMap.put(left, object);
				} else {
					left += ".";
					left += array[i];
				}
				if (i != array.length - 1) {
					if (objMap.get(left) == null) {
						Object beforeObj = objMap.get(beforeKey);
						Class beforeClass = beforeObj.getClass();
						Field field = beforeClass.getDeclaredField(array[i]);
						field.setAccessible(true);
						Class cls = field.getType();
						Object obj = cls.newInstance();
						objMap.put(left, obj);
						field.set(beforeObj, obj);
					}
				} else {
					Object beforeObj = objMap.get(beforeKey);
					injectField(array[i], value, beforeObj);
				}
				/*if (objMap.get(left) == null) {
					Object beforeObj = objMap.get(temp);
					Class beforeClass = classMap.get(temp);
					Field field = beforeClass.getDeclaredField(array[i]);
					field.setAccessible(true);
					cls = field.getClass();
					obj = cls.newInstance();
					objMap.put(left, obj);
					classMap.put(left, cls);
					field.set(beforeObj, obj);
				} else {
					obj = objMap.get(left);
					cls = classMap.get(left);
				}*/
			}
		}
		
		
		
		
		return (T) object;
		
	}
	
	public void injectField(String fieldName, String value, Object obj) { 
		try {
			Field field =  obj.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			Class type = field.getType();
			if (type == int.class || type == Integer.class) {
				field.setInt(obj, Integer.parseInt(value));
			} else if (type == long.class || type == Long.class) {
				field.setLong(obj, Long.parseLong(value));
			} else if (type == float.class || type == Float.class) {
				field.setFloat(obj, Float.parseFloat(value));
			} else if (type == double.class || type == Double.class) {
				field.setDouble(obj, Double.parseDouble(value));
			} else if (type == short.class || type == Short.class) {
				field.setShort(obj, Short.parseShort(value));
			} else if (type == byte.class || type == Byte.class) {
				field.setByte(obj, Byte.parseByte(value));
			} else if (type == boolean.class || type == Boolean.class) {
				field.setBoolean(obj, Boolean.parseBoolean(value));
			} else {
				field.set(obj, value);
			}
		} catch (Exception e) {
		}
	}
	
	public void injectObj(String fieldName, String value, Object obj, Class clazz, Map<String, Object> objMap) throws Exception {
		Field field = clazz.getDeclaredField(fieldName);
		field.setAccessible(true);
		Class inClass = field.getClass();
		Object inObj = null;
		if (objMap.get(fieldName) == null) {
			inObj = inClass.newInstance();
			objMap.put(fieldName, inObj);
		} else {
			inObj = objMap.get(fieldName);
		}
		field.set(inObj, value);
	}
	
	public static void main(String[] args) throws IOException, NumberFormatException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, IllegalArgumentException {
		ReadFile r = new ReadFile();
		String text = r.read(ReadFile.class.getClassLoader().getResourceAsStream("./datafile"));
		List<String> strList = r.getLine(text);
		Map<String, String> map = r.parseToMap(strList);
		A a = r.mapToObject(map, A.class);
		System.out.println(a);
	}
}
